package network;

public class MessageFactory {
	public synchronized static byte[] createHandshakePrefix(){
		byte[] handshakePrefix = new byte[20];
		//pstrlen
		handshakePrefix[0]=19;
		
		//pstr
		String s = "BitTorrent protocol";
		System.arraycopy(s.getBytes(), 0, handshakePrefix, 1, (s.getBytes()).length);	

		return	handshakePrefix;
	}
	
	public synchronized static byte[] createHandshake(byte[] infoHash, byte[] peerId){
		byte[] handshake = new byte[68];
		System.arraycopy(createHandshakePrefix(), 0, handshake, 0, 20);	
	
		//reserved bytes, set to 0
		for(int i=20 ; i<2 ; i++) handshake[i]=(byte)0;			
		
		//info_hash
		System.arraycopy(infoHash, 0, handshake, 28, infoHash.length); 
		//peer id
		System.arraycopy(peerId, 0, handshake, 48, peerId.length);
		
		return	handshake;
	}
	
	public synchronized static byte[] createKeepAlive() {
		byte[] keepAlive = new byte[4];
		//length prefix
		System.arraycopy(MessageTools.intToByteArray(0), 0, keepAlive, 0, 4);		
		return	keepAlive;
	}
	public synchronized static byte[] createChoke() {
		byte[] choke = new byte[5];
		//length prefix
		System.arraycopy(MessageTools.intToByteArray(1), 0, choke, 0, 4);
		//id
		choke[4]=(byte)0;		
		return	choke;
	}
	public synchronized static byte[] createUnchoke() {
		byte[] Unchoke = new byte[5];
		//length prefix
		System.arraycopy(MessageTools.intToByteArray(1), 0, Unchoke, 0, 4);
		//id
		Unchoke[4]=(byte)1;			
		return	Unchoke;
	}
	public synchronized static byte[] createInterested(){
		byte[] interested = new byte[5];
		//length prefix
		System.arraycopy(MessageTools.intToByteArray(1), 0, interested, 0, 4);		
		//id
		interested[4]=(byte)2;			
		return	interested;
	}
	public synchronized static byte[] createNotInterested(){
		byte[] notInterested = new byte[5];
		//length prefix
		System.arraycopy(MessageTools.intToByteArray(1), 0, notInterested, 0, 4);
		//id
		notInterested[4]=(byte)3;			
		return	notInterested;
	}
	public synchronized static byte[] createHave(int index){
		byte[] have = new byte[9];
		//length prefix
		System.arraycopy(MessageTools.intToByteArray(5), 0, have, 0, 4);
		//id
		have[4]=(byte)4;
		//index
		System.arraycopy(MessageTools.intToByteArray(index), 0, have, 5, 4);	
		return	have;
	}
	public synchronized static byte[] createBitfield(boolean[] pieces){
		//on fabrique le bitfield
		int bitfieldSize = pieces.length/8;
		if(pieces.length%8!=0)
			bitfieldSize++;
		//while(bitfieldSize%4!=0)
			//bitfieldSize++;
		
		byte[] bitfield = MessageTools.booleans2bytes(pieces);
		
		byte[] bitfieldMsg = new byte[5+bitfieldSize];
		java.util.Arrays.fill(bitfieldMsg,(byte)0);
		//length prefix
		System.arraycopy(MessageTools.intToByteArray(1+bitfieldSize), 0, bitfieldMsg, 0, 4);
		//id
		bitfieldMsg[4]=(byte)5;
		
		//bitfield
		System.arraycopy(bitfield, 0, bitfieldMsg, 5, bitfield.length);		
		return	bitfieldMsg;
	}
	public synchronized static byte[] createRequest(int index, int offset, int length){
		byte[] request = new byte[17];
		//length prefix
		System.arraycopy(MessageTools.intToByteArray(13), 0, request, 0, 4);
		//id
		request[4]=(byte)6;
		//index
		System.arraycopy(MessageTools.intToByteArray(index), 0, request, 5, 4);
		//offset
		System.arraycopy(MessageTools.intToByteArray(offset), 0, request, 9, 4);
		//length
		System.arraycopy(MessageTools.intToByteArray(length), 0, request, 13, 4);			
		return	request;
	}
	public synchronized static byte[] createPiece(byte[] index, byte[] begin, byte[] block){
		byte[] piece = new byte[13+block.length];
		//length prefix
		System.arraycopy(MessageTools.intToByteArray(9+block.length), 0, piece, 0, 4);
		//id
		piece[4]=(byte)7;
		//index
		System.arraycopy(index, 0, piece, 5, 4);
		//offset
		System.arraycopy(begin, 0, piece, 9, 4);
		//length
		System.arraycopy(block, 0, piece, 13, block.length);			
		return	piece;
	}
	public synchronized static byte[] createCancel(int index, int offset, int length){
		byte[] cancel = createRequest(index, offset, length);
		cancel[4]=(byte)8;
		return	cancel;
	}
}
